home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c-part1 / 3395 < prev    next >
Encoding:
Internet Message Format  |  1996-08-05  |  6.3 KB

  1. From: Marneffe_Thierry@msn.com (MARNEFFE Thierry G.)
  2. Subject: RE: PI Algorithm...
  3. Date: 28 Jan 96 14:14:12 -0800
  4. References: <4ebmpu$pde@news.iconn.net>
  5. Message-ID: <00001a80+0000733e@msn.com>
  6. Path: news.msn.com!msn.com
  7. Newsgroups: comp.lang.c
  8. Organization: The Microsoft Network (msn.com)
  9.  
  10.  
  11. PI Computing: here is a solution ( up to 64.000 digits)
  12.  
  13. Marneffe_Thierry@msn.com
  14. ------------------------
  15.  
  16. 1. Mathematical Background
  17. --------------------------
  18.  
  19.    Pi can be computed easily with the Stormer Formula:
  20.  
  21.      Pi = 24 arctg 1/8 + 8 arctg 1/57 + 4 arctg 1/239
  22.  
  23.    or the Gauss Formula:
  24.  
  25.      Pi = 48 arctg 1/18 + 32 arctg 1/57 - 20 arctg 1/239
  26.  
  27.    with
  28.                   1     1     1     1     1
  29.      arctg 1/x = --- - --- + --- - --- + --- ...
  30.                   X    3X3   5X5   7X7   9X9
  31.  
  32.    Considering the deinition of Arctg function, the Gauss formula 
  33.    is slightly faster than the Stormer Formula and is choosen for 
  34.    computation.
  35.  
  36.    Here is what you can expect with a 486 100 Mhz:
  37.  
  38.            1000 digits     1 seconds
  39.            2000 digits     4 seconds
  40.            4000 digits    14 seconds
  41.  
  42.  
  43. 2. Definitions and Declarations
  44. -------------------------------
  45.  
  46.   A. Data
  47.  
  48.     // Number of Decimals that must be computed ( multiple of 5)
  49.     long      m_lDecNbr;
  50.     
  51.     // Number of Terms to compute in the Gauss Formula to obtain the 
  52.     //        required number of exact digits
  53.     long      m_lTermNbr;
  54.  
  55.     // Pointer to Pi Digit Array
  56.     long*     m_plPi;               
  57.  
  58.   B. Functions
  59.  
  60.     // Allocate Memory for m_plPi Array 
  61.     //   Parameter: Ouput of GetArrayLen Function
  62.     BOOL  AllocPiMem( long lLen);
  63.  
  64.     // Free m_plPi Array
  65.     void  FreePiArray();    
  66.  
  67.     // Compute Pi (...)
  68.     void  ComputePi();
  69.            
  70.     // Get Length of Arrays for Storage of Pi and Temporary Digits
  71.     long  GetArrayLen()
  72.            { return (( m_lDecNbr / 4L)  + 5L); }
  73.     
  74.  
  75. 3. Source Code
  76. --------------
  77.  
  78. void ComputePi()
  79. {   
  80.  
  81.     // Utility Members
  82.  
  83.     long  lLen, lEvalTerm, lTerm, lDivider, lRemainder;
  84.     long  lComputedTerm, lEndTerm, lTermSum, lFinalSum, lFinalTerm;
  85.     long  lStartTerm1, lStartTerm2, lStartTerm3, lDiv1, lDiv2, lDiv3;
  86.     
  87.     // Flag for Operation Type ( Addition or Soustraction)
  88.  
  89.     BOOL  bAdd;
  90.     
  91.     // Array for Storage of Intermediate Computations
  92.     long* plArctg1;
  93.     long* plArctg2;
  94.     long* plArctg3;                        
  95.     
  96.  
  97.     // Alloc Array for Pi Storage
  98.     
  99.     lLen = GetArrayLen();
  100.     
  101.     if ( !AllocPiMem( lLen))
  102.         return;
  103.  
  104.     // Allocate Memory for Intermediary Data 
  105.     
  106.     plArctg1 = new long[lLen];
  107.     plArctg2 = new long[lLen];
  108.     plArctg3 = new long[lLen];
  109.  
  110.     // Init Array
  111.     
  112.     for ( long i = 0L; i < lLen; i++)
  113.     {   
  114.         plArctg1[i] = 0L;
  115.         plArctg2[i] = 0L;
  116.         plArctg3[i] = 0L;    
  117.     }
  118.     
  119.     bAdd = TRUE;
  120.  
  121.     //Set Starting Value for Terms Computing 
  122.  
  123.     plArctg1[0] = 864L;        /* 48  * 18  */
  124.     plArctg2[0] = 1824L;       /* 32  * 57  */
  125.     plArctg3[0] = 4780L;       /* 20  * 239 */
  126.  
  127.     // Set Dividers 
  128.  
  129.     lDiv1 = 324L;              /*  18 * 18  */
  130.     lDiv2 = 3249L;             /*  57 * 57  */
  131.     lDiv3 = 57121L;            /* 239 * 239 */
  132.  
  133.     // Set Start and End Term 
  134.     
  135.     lStartTerm1 = 0L;    
  136.     lStartTerm2 = 0L;
  137.     lStartTerm3 = 0L;
  138.  
  139.     lEndTerm = m_lTermNbr;
  140.     
  141.     lEvalTerm = ( m_lDecNbr / 4L) + 5L;
  142.     
  143.     // Start Computing 
  144.     
  145.     lDivider = 1L;
  146.     
  147.     lComputedTerm = 0L;
  148.     
  149.     while ( lComputedTerm < lEndTerm)
  150.     {
  151.  
  152.         // Compute Series for Term Arctg 1/18 
  153.  
  154.         lRemainder = 0L;
  155.  
  156.         for ( lTerm = lStartTerm1; lTerm < lEvalTerm; lTerm++)
  157.         {
  158.             lTermSum = ( lRemainder * 10000L) + plArctg1[lTerm];
  159.  
  160.             plArctg1[lTerm] = lTermSum / lDiv1;
  161.  
  162.             lRemainder = lTermSum - ( plArctg1[lTerm] * lDiv1);
  163.         }
  164.         
  165.         // Compute Series for Term Arctg 1/57 
  166.  
  167.         lRemainder = 0L;
  168.  
  169.         for ( lTerm = lStartTerm2; lTerm < lEvalTerm; lTerm++)
  170.         {
  171.             lTermSum = ( lRemainder * 10000L) + plArctg2[lTerm];
  172.  
  173.             plArctg2[lTerm] = lTermSum / lDiv2;
  174.  
  175.             lRemainder = lTermSum - ( plArctg2[lTerm] * lDiv2);
  176.         }
  177.         
  178.         if ( lStartTerm2 < lEvalTerm)
  179.             if ( plArctg2[lStartTerm2] == 0L)
  180.                 lStartTerm2 += 1L;
  181.  
  182.         // Compute Series for Term Arctg 1/239 
  183.  
  184.         lRemainder = 0L;
  185.  
  186.         for ( lTerm = lStartTerm3; lTerm < lEvalTerm; lTerm++)
  187.         {
  188.             lTermSum = ( lRemainder * 10000L) + plArctg3[lTerm];
  189.  
  190.             plArctg3[lTerm] = lTermSum / lDiv3;
  191.  
  192.             lRemainder = lTermSum - ( plArctg3[lTerm] * lDiv3);
  193.         }
  194.         
  195.         if ( lStartTerm3 < lEvalTerm)
  196.             if ( plArctg3[lStartTerm3] == 0L)
  197.                 lStartTerm3 += 1L;
  198.  
  199.         // Compute Sum of Terms 
  200.  
  201.         lRemainder = 0L;
  202.  
  203.         for ( lTerm = lStartTerm1; lTerm < lEvalTerm; lTerm++)
  204.         {   
  205.             // Add Arctg series 
  206.  
  207.             if ( bAdd)
  208.                lTermSum = plArctg1[lTerm] + plArctg2[lTerm] - plArctg3[lTerm];
  209.             else
  210.                lTermSum = plArctg3[lTerm] - plArctg1[lTerm] - plArctg2[lTerm];
  211.             
  212.             lFinalSum = ( lRemainder * 10000L) + lTermSum;
  213.  
  214.             lFinalTerm = lFinalSum / lDivider;
  215.             
  216.             lRemainder = lFinalSum - ( lFinalTerm * lDivider);
  217.             
  218.             // Add Series Sum to Current Value 
  219.             
  220.             m_plPi[lTerm] = m_plPi[lTerm] + lFinalTerm;
  221.  
  222.             // Check for Carry Over 
  223.             
  224.             if ( m_plPi[lTerm] < 0L)
  225.             {               
  226.                 m_plPi[lTerm] += 10000L;
  227.                 m_plPi[lTerm - 1L] -= 1L;
  228.             }
  229.             else if ( m_plPi[lTerm] > 10000L)
  230.             {
  231.                 m_plPi[lTerm] -= 10000L;
  232.                 m_plPi[lTerm - 1L] += 1L;
  233.             }
  234.         }
  235.  
  236.         // Update Index of First Term to compute if required 
  237.         // This allow substantial reduction of computing time as this
  238.         // avoid working on terms equal to 0L
  239.  
  240.         if ( lStartTerm1 < lEvalTerm)
  241.             if ( plArctg1[lStartTerm1] == 0L) 
  242.                 lStartTerm1 += 1L;
  243.             
  244.         lComputedTerm += 1L;
  245.         
  246.         lDivider += 2L;
  247.         
  248.         // Reverse Sign for Arctg series
  249.  
  250.         bAdd = bAdd ? FALSE : TRUE;
  251.  
  252.     }
  253.     
  254.     // Clean Up 
  255.     
  256.     delete [] plArctg1;
  257.     delete [] plArctg2;
  258.     delete [] plArctg3;
  259. }
  260.  
  261.